function merge(o1, o2) {
	for (const p in o2) o1[p] = typeof o1[p] != 'undefined' ? o1[p] : o2[p];
	return o1;
}

function clone(o) {
	const newObject = {};
	for (const p in o) newObject[p] = o[p];
	return newObject;
}

function extend(to, from) {
	for (const key in from) {
		to[key] = from[key];
	}
	return to;
}

function isArray(a) {
	return Array.isArray(a);
}

function isObject(a) {
	return a === Object(a) && !isArray(a) && typeof a === 'object';
}

function isSvg(a) {
	return a instanceof SVGElement;
}

function isDom(a) {
	return a.nodeType || isSvg(a);
}

function isNumber(a) {
	return !isNaN(parseInt(a));
}

function isString(a) {
	return typeof a === 'string';
}

function isFunction(a) {
	return typeof a === 'function';
}

function isUndefined(a) {
	return typeof a === 'undefined';
}

function isNull(a) {
	return a === null;
}

function isArrayEqual(...args) {
	const array1 = args.length > 0 && args[0] !== undefined ? args[0] : [];
	const array2 = args.length > 1 && args[1] !== undefined ? args[1] : [];
	if (array1 === array2) return true;
	return array1.length === array2.length && array1.every((item, index) => item === array2[index]);
}

function isObjectEqual(obj1, obj2) {
	if (!isObject(obj1) || !isObject(obj2)) {
		return false;
	}
	if (obj1 === obj2) return true;
	const item1Keys = Object.keys(obj1).sort();
	const item2Keys = Object.keys(obj2).sort();
	if (!isArrayEqual(item1Keys, item2Keys)) return false;
	return item2Keys.every((key) => {
		const value = obj1[key];
		const nextValue = obj2[key];
		if (value === nextValue) {
			return true;
		}
		return isArray(value) && isArray(nextValue) && isArrayEqual(value, nextValue);
	});
}

export {
	merge,
	clone,
	extend,
	isArray,
	isObject,
	isSvg,
	isDom,
	isNumber,
	isString,
	isFunction,
	isUndefined,
	isNull,
	isArrayEqual,
	isObjectEqual
};
